package com.trust.pams.dao.mongo;

import com.chasonx.common.reference.EntityAttribute;
import com.chasonx.common.util.ReferenceUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * @Project : tscp-platform
 * @Author : Chasonx<zc.x>
 * @CreateTime : 2020/5/6 14:54
 * @Desc :
 * @Version : 1.0
 */
public class BaseMongoDaoImpl<T> {

    @Autowired
    private MongoTemplate mongoTemplate;

    public List<T> findAll(){
        return (List<T>) mongoTemplate.findAll( getCurrentClass() );
    }

    public T findById(Object id){
        return mongoTemplate.findById(id , getCurrentClass());
    }

    public void insert(T t){
        mongoTemplate.insert(t);
    }

    public void insertAll(List<T> list){
        mongoTemplate.insertAll(list);
    }

    public boolean deleteAll(){
       return mongoTemplate.remove(new Query(),getCurrentClass()).getDeletedCount() > 0;
    }

    public boolean deleteById(Object id){
        Query query = new Query(Criteria.where("_id").is(id));
        return mongoTemplate.remove(query,getCurrentClass()).getDeletedCount() > 0;
    }

    public boolean updateById(T t , Object id){
        EntityAttribute attribute = ReferenceUtil.getEntitiyAttribute(t);
        Query query = new Query(Criteria.where("_id").is(id));
        Update update = new Update();
        for(int i = 0,len = attribute.getFields().size();i < len;i++){
            update.set(attribute.getFields().get(i) , attribute.getValues().get(i));
        }
        return mongoTemplate.updateFirst(query , update , getCurrentClass()).getModifiedCount() > 0;
    }

    public long upsert(Query query,T t){
        return upsert(query , t , getCurrentClass());
    }

    public long upsert(Query query,Object t , Class<?> cls){
        EntityAttribute attribute = ReferenceUtil.getEntitiyAttribute(t);
        Update update = new Update();
        for(int i = 0,len = attribute.getFields().size();i < len;i++){
            update.set(attribute.getFields().get(i) , attribute.getValues().get(i));
        }
        return mongoTemplate.upsert(query, update ,cls).getModifiedCount();
    }

    public MongoTemplate getMongoTemplate(){
        return mongoTemplate;
    }

    public List<T> find(Query query){
        return mongoTemplate.find(query , getCurrentClass());
    }

    public List<T> find(BasicQuery query){
        return mongoTemplate.find(query , getCurrentClass());
    }

    public Class<T> getCurrentClass(){
        return  (Class<T>) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public String getCollectionName(){
       return getCollectionName(getCurrentClass());
    }

    public String getCollectionName(Class<?> cls){
        Document document = cls.getAnnotation(Document.class);
        if(null == document){
            return null;
        }
        return document.collection();
    }

}
